package lelouet.sh3d.plugins.sweetDatacenter.gui;

import java.util.ArrayList;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JPanel;

import lelouet.sh3d.plugins.sweetDatacenter.model.GRack;
import lelouet.sh3d.plugins.sweetDatacenter.model.GServer;
import lelouet.sh3d.plugins.sweetDatacenter.model.GridGraphicalBridge;

import com.eteks.sweethome3d.model.SelectionEvent;
import com.eteks.sweethome3d.model.SelectionListener;

/**
 * a panel that shows the datacenter informations about the element that is now
 * selected<br />
 * 
 * the use cases :
 * <ul>
 * <li>A new element is selected. this is told to show this element's
 * informations</li>
 * <li>An element, that is selected, is modified. This is told to show this
 * element's informations, modified.</li>
 * </ul>
 */
public class SelectedElementPane extends JPanel {

	private static final long serialVersionUID = 1L;

	/** panel that shows informations about a server */
	protected ServerPropertiesPanel serverPanel;

	/** panel that shows informations about a rack */
	protected RackPropertiesPanel rackPanel;

	/** panel that tells nothing is selected */
	protected JPanel nothingPanel;

	protected JPanel createNothingPanel() {
		JPanel panel = new JPanel();
		JLabel label = new JLabel("nothing selected");
		panel.add(label);
		return panel;
	}

	protected GridGraphicalBridge bridge;

	public SelectedElementPane(GridGraphicalBridge bridge) {
		this.bridge = bridge;
		init_gui();
		elementUnselected();
	}

	public void selectVisiblePane(JPanel panel) {
		serverPanel.setVisible(false);
		rackPanel.setVisible(false);
		nothingPanel.setVisible(false);
		panel.setVisible(true);
		// setSize(panel.getSize());
	}

	/**
	 * To call when a {@link GServer} is selected or modified in the graphical
	 * window.
	 */
	public void showServerInfos(GServer toShow) {
		selectVisiblePane(serverPanel);
		serverPanel.updateServer(toShow);
	}

	/**
	 * to call when a {@link GRack} is selected or modified in the graphical
	 * window.
	 */
	public void showRackInfos(GRack toShow) {
		selectVisiblePane(rackPanel);
		rackPanel.updateRack(toShow);
	}

	/** to call when the previously selected element is no more selected. */
	public void elementUnselected() {
		selectVisiblePane(nothingPanel);
	}

	public class MControler implements SelectionListener {

		public static final String NO_MODEL_STRING = "no model used";

		protected MControler() {
		}

		protected Object lastSelected = null;
		protected GServer serverSelected = null;
		protected GRack rackSelected = null;

		protected void setRackAndServerSelected(GRack rack, GServer server) {
			rackSelected = rack;
			serverSelected = server;
			if (serverSelected != null) {
				lastSelected = serverSelected;
			} else {
				lastSelected = rack;
			}
		}

		@Override
		public void selectionChanged(SelectionEvent event) {
			java.util.List<?> selectedItems = event.getSelectedItems();
			if (selectedItems.isEmpty() || selectedItems.size() > 1) {
				if (lastSelected != null) {
					elementUnselected();
					lastSelected = null;
				}
			} else {
				Object selected = selectedItems.get(0);
				if (lastSelected == selected) {
					return;
				}
				if (selected instanceof GRack) {
					GRack rack = (GRack) selected;
					setRackAndServerSelected(rack, null);
					showRackInfos(rack);
				} else if (selected instanceof GServer) {
					GServer server = (GServer) selected;
					setRackAndServerSelected(null, server);
					showServerInfos(server);
				} else {
					setRackAndServerSelected(null, null);
					elementUnselected();
				}
			}
		}

		public void setCPUCapacity(String capacity) {
			if (serverSelected != null) {
				try {
					serverSelected.setCPUCapacity(Double.parseDouble(capacity));
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setCPUNumber(String number) {
			if (serverSelected != null) {
				try {
					serverSelected.setCPUNumber(Double.parseDouble(number));
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setMemoryCapacity(String capacity) {
			if (serverSelected != null) {
				try {
					serverSelected.setMemoryCapacity(Double
							.parseDouble(capacity));
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setVSize(String vsize) {
			if (serverSelected != null) {
				try {
					serverSelected.setVSize(Integer.parseInt(vsize));
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setOsFamily(String family) {
			if (serverSelected != null) {
				try {
					serverSelected.setOSFamily(family);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setOsDistrib(String distrib) {
			if (serverSelected != null) {
				try {
					serverSelected.setOSDistrib(distrib);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setName(String name) {
			if (serverSelected != null) {
				try {
					serverSelected.setName(name);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setServerIp(String ip) {
			if (serverSelected != null) {
				try {
					serverSelected.setIP(ip);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setServerMac(String mac) {
			if (serverSelected != null) {
				try {
					serverSelected.setMac(mac);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setRackSize(String size) {
			if (rackSelected != null) {
				try {
					rackSelected.setLvlNb(Integer.parseInt(size));
					showRackInfos(rackSelected);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		protected void swapServers(int posLowServer, GServer lowServer,
				int posHighServer, GServer highServer) {
			if (lowServer == highServer) {
				return;
			}
			rackSelected.unsetServer(highServer);
			rackSelected.unsetServer(lowServer);

			if (highServer != null) {
				rackSelected.addServer(highServer, posLowServer);
			}
			int posToAdd = posLowServer + 1;
			if (highServer != null) {
				posToAdd = posLowServer + highServer.getVSize();
			}
			if (lowServer != null) {
				rackSelected.addServer(lowServer, posToAdd);
			}
			showRackInfos(rackSelected);
		}

		public void moveGServerUp(int serverLevel) {
			if (rackSelected != null) {
				try {
					GServer server = rackSelected.serverAtLvl(serverLevel);
					int nextPos = serverLevel + 1;
					if (server != null) {
						nextPos = serverLevel + server.getVSize();
					}
					if (nextPos >= rackSelected.getLvlNb()) {
						return;
					}
					GServer otherServer = rackSelected.serverAtLvl(nextPos);
					swapServers(serverLevel, server, nextPos, otherServer);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void moveGServerDown(int serverLevel) {
			if (rackSelected != null) {
				try {
					GServer server = rackSelected.serverAtLvl(serverLevel);
					int nextPos = serverLevel - 1;
					if (nextPos < 0) {
						return;
					}
					GServer lowServer = rackSelected.serverAtLvl(nextPos);
					if (lowServer != null) {
						nextPos = serverLevel - lowServer.getVSize();
					}
					swapServers(nextPos, lowServer, serverLevel, server);
				} catch (Exception ex) {
					ex.printStackTrace(System.err);
				}
			}
		}

		public void setSelectedServer(GServer describedServer) {
			bridge.selectServer(describedServer);
		}

		public void renameRackServers() {
			if (rackSelected != null) {
				rackSelected.renameServers();
			}
		}

		public void setRackName(String text) {
			if (rackSelected != null) {
				rackSelected.setName(text);
			}
		}

		public void setServerModel(String selectedName) {
			serverSelected.setGridModel(bridge.getModelByName(selectedName));
		}

		public String[] getAvailableModels() {
			List<String> ret = new ArrayList<String>();
			ret.add(NO_MODEL_STRING);
			for (String name : bridge.getModelsNames()) {
				ret.add(name);
			}
			return ret.toArray(new String[] {});
		}
	}

	protected MControler controler = new MControler();

	public MControler getControler() {
		return controler;
	}

	private void init_gui() {
		serverPanel = new ServerPropertiesPanel();
		serverPanel.setControler(getControler());
		add(serverPanel);
		rackPanel = new RackPropertiesPanel();
		rackPanel.setControler(getControler());
		add(rackPanel);
		nothingPanel = createNothingPanel();
		add(nothingPanel);

	}

}
